#!/usr/bin/env python3
"""
Generate a Markdown grid of contributor avatars for a GitHub repository.

Usage:
    python generate_contributors_grid.py --repo owner/name --token GH_TOKEN [--cols 7] [--image_size 80] [--output FILE]

Arguments:
  --repo         GitHub repository in "owner/name" form (e.g. "octocat/Hello-World")
  --token        Personal access token with `public_repo` scope (or `repo` for private).
                 Can also be provided via the GITHUB_TOKEN environment variable.
  --cols         Number of avatars per row in the generated grid (default 7).
  --image_size   Pixel width for avatars (GitHub automatically resizes; default 80).
  --output       File to write the Markdown grid into (default: stdout, use '-' for stdout).

The generated file contains a Markdown table‑less grid of linked avatars that can
be embedded in README.md or any other Markdown document.
"""

from __future__ import annotations
import argparse
import os
import sys
import textwrap
from typing import List, Dict

import requests

API_URL_TEMPLATE = "https://api.github.com/repos/{owner}/{repo}/contributors"


def fetch_contributors(owner: str, repo: str, token: str | None, per_page: int = 100) -> List[Dict]:
    """Return a list of contributor objects from the GitHub REST API."""
    headers = {"Accept": "application/vnd.github+json"}
    if token:
        headers["Authorization"] = f"Bearer {token}"

    contributors: List[Dict] = []
    page = 1
    while True:
        url = f"{API_URL_TEMPLATE.format(owner=owner, repo=repo)}?per_page={per_page}&page={page}"
        response = requests.get(url, headers=headers, timeout=10)
        response.raise_for_status()
        batch = response.json()
        if not batch:
            break
        contributors.extend(batch)
        if len(batch) < per_page:
            break
        page += 1
    return contributors


def build_markdown(contributors: List[Dict], cols: int = 7, image_size: int = 80) -> str:
    """Return a Markdown fragment containing a grid of linked avatar images."""
    lines: List[str] = []
    row: List[str] = []

    for contributor in contributors:
        login = contributor["login"]
        avatar = f"{contributor['avatar_url']}&s={image_size}"
        profile = contributor["html_url"]
        cell = f'[<img src="{avatar}" width="{image_size}px" alt="{login}" />]({profile})'
        row.append(cell)
        if len(row) == cols:
            lines.append(" ".join(row))
            row = []

    if row:
        lines.append(" ".join(row))

    return "\n\n".join(lines)


def main() -> None:
    parser = argparse.ArgumentParser(description="Generate a Markdown grid of contributor avatars")
    parser.add_argument("--repo", required=True, help="GitHub repo in owner/name form")
    parser.add_argument("--token", help="GitHub Personal Access Token (or set GITHUB_TOKEN env)")
    parser.add_argument("--cols", type=int, default=7, help="Number of avatars per row (default 7)")
    parser.add_argument("--image_size", type=int, default=80, help="Avatar size in px (default 80)")
    parser.add_argument("--output", "-o", default="-", help="Output file (default: stdout, use '-' for stdout)")

    args = parser.parse_args()
    token = args.token or os.getenv("GITHUB_TOKEN")
    if not token:
        parser.error("A GitHub token must be supplied via --token or GITHUB_TOKEN env var.")

    if "/" not in args.repo:
        parser.error("--repo must be in 'owner/name' form")
    owner, repo = args.repo.split("/", 1)

    contributors = fetch_contributors(owner, repo, token)
    if not contributors:
        sys.exit("No contributors found. Is the repository correct and does the token have access?")

    markdown = build_markdown(contributors, cols=args.cols, image_size=args.image_size)

    header = textwrap.dedent(
        f"""
        <!-- AUTO-GENERATED BY generate_contributors_grid.py -->
        ## Contributors
        Thanks to these wonderful people:\n
        """
    )

    if args.output == "-":
        sys.stdout.write(header)
        sys.stdout.write(markdown)
        sys.stdout.write("\n")
    else:
        with open(args.output, "w", encoding="utf-8") as fh:
            fh.write(header)
            fh.write(markdown)
            fh.write("\n")
        print(f"Wrote {len(contributors)} contributors to {args.output}", file=sys.stderr)


if __name__ == "__main__":
    main()

